/*************************************************************
 *Name:           Christopher Alexander
 *Email address:  alexanc2@onid.oregonstate.edu
 *Class name:     CS362-400
 *Assignment:     Team 9 - Project Test scoreFor()
 *Description:    The program will peform unit testing on the
 *                dominion.c function scoreFor().
 *************************************************************/

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"

/*Function Prototypes*/
int preScoreFor (int, struct gameState *preState);
int checkScoreFor(int, struct gameState *testState);


/*This function is used to generate a value for score that
 *should be identical to the value calculated by scoreFor()
 *Params: p - the player to check the score of.
 *        preState - a pointer to a struct gameState that contains.
                     a score to be calculated.
 *Return: the score of player p.
 */
int preScoreFor (int p, struct gameState *preState) {

   int i;
   int score = 0;

   //score from hand
   for (i = 0; i < preState->handCount[p]; i++){
      if (preState->hand[p][i] == curse) { score = score - 1; };
      if (preState->hand[p][i] == estate) { score = score + 1; };
      if (preState->hand[p][i] == duchy) { score = score + 3; };
      if (preState->hand[p][i] == province) { score = score + 6; };
      if (preState->hand[p][i] == great_hall) { score = score + 1; };
      if (preState->hand[p][i] == gardens) { score = score + ( fullDeckCount(p, 0, preState) / 10 ); };
   }

   //score from discard
   for (i = 0; i < preState->discardCount[p]; i++){
      if (preState->discard[p][i] == curse) { score = score - 1; };
      if (preState->discard[p][i] == estate) { score = score + 1; };
      if (preState->discard[p][i] == duchy) { score = score + 3; };
      if (preState->discard[p][i] == province) { score = score + 6; };
      if (preState->discard[p][i] == great_hall) { score = score + 1; };
      if (preState->discard[p][i] == gardens) { score = score + ( fullDeckCount(p, 0, preState) / 10 ); };
   }

   //score from deck
   for (i = 0; i < preState->deckCount[p]; i++){
      if (preState->deck[p][i] == curse) { score = score - 1; };
      if (preState->deck[p][i] == estate) { score = score + 1; };
      if (preState->deck[p][i] == duchy) { score = score + 3; };
      if (preState->deck[p][i] == province) { score = score + 6; };
      if (preState->deck[p][i] == great_hall) { score = score + 1; };
      if (preState->deck[p][i] == gardens) { score = score + ( fullDeckCount(p, 0, preState) / 10 ); };
   }
   return score;
}


/*This function will calculate the score of a player in two ways,
 *and then compare the results to make sure they are the same.
 *1)The scoreFor() function of dominion.c will be used to calculate score.
 *2)The score will be calculated using the preScoreFor() function here.
 *Params: p - the player to check the score of.
 *        preState - a pointer to a struct gameState that contains.
 *                   a score to be calculated.
 *Return: the score of player p.
 */
int checkScoreFor(int p, struct gameState *testState) {
   int testScore, preScore;
   struct gameState preState;

   memcpy(&preState, testState, sizeof(struct gameState));

   //Calculate the score in two different ways.
   preScore = preScoreFor(p, &preState);
   testScore = scoreFor(p, testState);

   //Check that the same score was calculated both ways.
   assert(preScore == testScore);

   return testScore;
}


int main() {
   int i, n, p;
   struct gameState G;

   /*These are the cards that scoreFor checks. This array will be used to
   randomly assign a card to G.deck, G.discard, and G.hand */
   int scoreCards[6] = {curse, estate, duchy, province, great_hall, gardens};
   int randomCard;

   printf("\nTesting scoreFor():\n");

   for (n = 0; n < 2000; n++) {
      for (i = 0; i < sizeof(struct gameState); i++){
         ((char*)&G)[i] = (int) (Random() * 256);
      }

      p = (int) (Random() * 2); //Randomly determine player.

      //Randomly set size of deck, discard, and hand.
      G.deckCount[p] = (int) (Random() * MAX_DECK);
      G.discardCount[p] = (int) (Random() * MAX_DECK);
      G.handCount[p] = (int) (Random() * MAX_DECK);

      //Randomly fill deck, discard, and hand with scoring cards.
      for (i = 0; i < G.deckCount[p]; i++){
         randomCard = (int) (Random() * 6);
         G.deck[p][i] = scoreCards[randomCard];
      }
      for (i = 0; i < G.discardCount[p]; i++){
         randomCard = (int) (Random() * 6);
         G.discard[p][i] = scoreCards[randomCard];
      }
      for (i = 0; i < G.handCount[p]; i++){
         randomCard = (int) (Random() * 6);
         G.hand[p][i] = scoreCards[randomCard];
      }

      checkScoreFor(p, &G);
   }
   printf("All tests of scoreFor() passed!\n");
   return 0;
}
